/**
 * TODO Documentation if InferenceDataImporter
 */
package br.unb.graphics.inference;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;

import br.unb.graphics.GraphicInterface;
import br.unb.graphics.InterfaceFactory;
import br.unb.statistic.inference.Inference;
import br.unb.statistic.inference.dataReader.DataReader;
import br.unb.utils.Console;
import br.unb.utils.Resource;

public class InferenceDataImporter extends JFrame {

    private File file;
    private JPanel textPanel, buttonsPanel, firstTopPanel, secondTopPanel;
    private JTable table;
    private JTextField delimiterField, columnField, commentaryField, timeUnitField;
    private JButton okButton, cancelButton;
    private boolean isFirstPanel = true;
    private JRadioButton otherRadioButton, interPacketTimeRadio, incrementProcessRadio, columnValuesRadio;
    private JScrollPane scrollPane;
    private JLabel timeUnitLabel;
    private String iteratorChar = "\t";
    private String commentaryCharacter = "#";
    private int columns, maxColumns;
    private double timeUnitValue = 1000000;
    public static final Dimension secondPaneDimension = new Dimension(480, 630);
    public static final Dimension firstPaneDimension = new Dimension(500, 580);
    private InterfaceFactory iFactory;
    private Action[] defaultActions = {
        new OkAction(),
        new CancelAction(),
        new DetailsAction(),
        new TabAction(),
        new SemicolonAction(),
        new SpaceAction(),
        new OtherAction(),
        new ColumnValuesAction(),
        new InterPacketTimesAction(),
        new PacketsPerTimeUnitAction(),};
    private static final String frameTitle = "frameTitle";
    private static final String ok = "okButton";
    private static final String cancel = "cancelButton";
    private static final String delimiter = "delimiter";
    private static final String tab = "tab";
    private static final String semicolon = "semicolon";
    private static final String space = "space";
    private static final String other = "other";
    private static final String commentaryChar = "commentaryChar";
    private static final String column = "column";
    private static final String columnLabel = "columnLabel";
    private static final String dataPreview = "dataPreview";
    private static final String columnValues = "columnValues";
    private static final String interPacketTimes = "interPacketTimes";
    private static final String packetsPerTimeUnit = "packetsPerTimeUnit";
    private static final String timeUnit = "timeUnit";
    private static final String details = "detailsButton";
    private static final String error = "error";
    private static final String errorTitle = "errorTitle";
    private static final String SAMPLES_LABEL = "samplesLabel";
    private static final String okAction = "okAction";
    private static final String cancelAction = "cancelAction";
    private static final String detailsAction = "detailsAction";
    private static final String tabAction = "tabAction";
    private static final String semicolonAction = "semicolonAction";
    private static final String spaceAction = "spaceAction";
    private static final String otherAction = "otherAction";
    private static final String columnValuesAction = "columnValuesAction";
    private static final String interPacketTimesAction = "interPacketTimesAction";
    private static final String packetsPerTimeUnitAction = "packetsPerTimeUnitAction";
    private static final String delimiterFieldAction = "delimiterFieldAction";
    private static final String columnFieldAction = "columnFieldAction";
    private static final String commentaryFieldAction = "commentaryFieldAction";
    private static final String timeUnitFieldAction = "timeUnitFieldAction";

    public InferenceDataImporter(File file) {
        super();

        this.iFactory = new InterfaceFactory(Resource.InferenceDataImporter, defaultActions);
        this.setTitle(iFactory.getResourceString(InferenceDataImporter.frameTitle));

        this.file = file;

        this.delimiterField = new JTextField(2);
        this.delimiterField.addActionListener(new DelimiterFieldAction());
        this.delimiterField.setActionCommand(delimiterFieldAction);

        this.columnField = new JTextField(4);
        this.columnField.addActionListener(new ColumnFieldAction());
        this.columnField.setActionCommand(columnFieldAction);

        this.commentaryField = new JTextField(2);
        this.commentaryField.addActionListener(new CommentaryFieldAction());
        this.commentaryField.setActionCommand(commentaryFieldAction);
        this.commentaryField.setText("#");

        this.okButton = iFactory.createButton(InferenceDataImporter.ok);
        this.okButton.setEnabled(false);
        this.cancelButton = iFactory.createButton(InferenceDataImporter.cancel);

        this.buttonsPanel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.EAST;
        c.gridx = 0;
        c.gridy = 0;
        buttonsPanel.add(this.okButton, c);
        c.gridx = 1;
        buttonsPanel.add(this.cancelButton, c);

        JRadioButton tab = iFactory.createRadioButton(InferenceDataImporter.tab, true);
        JRadioButton semiColon = iFactory.createRadioButton(InferenceDataImporter.semicolon, false);
        JRadioButton space = iFactory.createRadioButton(InferenceDataImporter.space, false);
        this.otherRadioButton = iFactory.createRadioButton(InferenceDataImporter.other, false);
        ButtonGroup delimiterBG = new ButtonGroup();
        delimiterBG.add(tab);
        delimiterBG.add(space);
        delimiterBG.add(semiColon);
        delimiterBG.add(this.otherRadioButton);

        JPanel delimiterPanel = new JPanel(new GridBagLayout());
        c.anchor = GridBagConstraints.WEST;
        c.gridx = 0;
        c.gridy = 0;
        delimiterPanel.add(iFactory.createLabel(InferenceDataImporter.delimiter), c);
        c.gridy = 1;
        delimiterPanel.add(tab, c);
        c.gridy = 2;
        delimiterPanel.add(semiColon, c);
        c.gridx = 1;
        c.gridy = 1;
        delimiterPanel.add(space, c);
        c.gridx = 1;
        c.gridy = 2;
        delimiterPanel.add(this.otherRadioButton, c);
        c.gridx = 2;
        delimiterPanel.add(this.delimiterField, c);

        JPanel columnPanel = new JPanel(new BorderLayout());
        columnPanel.add(BorderLayout.WEST, iFactory.createLabel(InferenceDataImporter.columnLabel));
        columnPanel.add(BorderLayout.CENTER, this.columnField);

        JPanel commentaryPanel = new JPanel(new BorderLayout());
        commentaryPanel.add(BorderLayout.WEST, iFactory.createLabel(InferenceDataImporter.commentaryChar));
        commentaryPanel.add(BorderLayout.CENTER, this.commentaryField);

        JPanel topLeftPanel = new JPanel(new GridBagLayout());
        c.gridx = 0;
        c.gridy = 0;
        topLeftPanel.add(Box.createRigidArea(new Dimension(20, 18)), c);
        c.gridx = 1;
        c.gridy = 1;
        topLeftPanel.add(columnPanel, c);
        c.gridy = 2;
        topLeftPanel.add(Box.createRigidArea(new Dimension(20, 5)), c);
        c.gridy = 3;
        topLeftPanel.add(commentaryPanel, c);


        this.columnValuesRadio = iFactory.createRadioButton(InferenceDataImporter.columnValues, true);
        this.interPacketTimeRadio = iFactory.createRadioButton(InferenceDataImporter.interPacketTimes, false);
        this.incrementProcessRadio = iFactory.createRadioButton(InferenceDataImporter.packetsPerTimeUnit, false);

        this.timeUnitField = new JTextField(8);
        this.timeUnitField.setText("" + this.timeUnitValue);

        this.timeUnitField.setActionCommand(InferenceDataImporter.timeUnitFieldAction);
        this.timeUnitField.addActionListener(new TimeUnitFieldAction());

        ButtonGroup processBG = new ButtonGroup();
        processBG.add(this.columnValuesRadio);
        processBG.add(this.interPacketTimeRadio);
        processBG.add(this.incrementProcessRadio);
        JButton detailsButton = iFactory.createButton(InferenceDataImporter.details);

        this.timeUnitLabel = iFactory.createLabel(InferenceDataImporter.timeUnit);

        JPanel timeUnitPanel = new JPanel(new GridBagLayout());
        c.gridx = 0;
        c.gridy = 0;
        timeUnitPanel.add(new JLabel("       "), c);
        c.gridx = 1;
        timeUnitPanel.add(this.timeUnitLabel, c);
        c.gridx = 2;
        timeUnitPanel.add(this.timeUnitField, c);

        this.timeUnitField.setEnabled(false);
        this.timeUnitLabel.setEnabled(false);

        this.secondTopPanel = new JPanel(new GridBagLayout());
        c.gridy = 0;
        c.gridx = 0;
        this.secondTopPanel.add(iFactory.createLabel(InferenceDataImporter.SAMPLES_LABEL), c);
        c.gridy = 1;
        this.secondTopPanel.add(this.columnValuesRadio, c);
        c.gridy = 2;
        this.secondTopPanel.add(this.interPacketTimeRadio, c);
        c.gridy = 3;
        this.secondTopPanel.add(this.incrementProcessRadio, c);
        c.gridy = 4;
        this.secondTopPanel.add(timeUnitPanel, c);
        c.gridy = 5;
        this.secondTopPanel.add(detailsButton, c);

        this.firstTopPanel = new JPanel(new BorderLayout());
        firstTopPanel.add(BorderLayout.WEST, delimiterPanel);
        firstTopPanel.add(BorderLayout.CENTER, Box.createRigidArea(new Dimension(2, 2)));
        firstTopPanel.add(BorderLayout.EAST, topLeftPanel);
        this.getContentPane().setLayout(new GridBagLayout());
        c.gridy = 0;
        c.gridx = 0;
        this.getContentPane().add(firstTopPanel, c);
        this.refreshTable(file);
        c.gridy = 2;
        c.gridx = 0;
        this.getContentPane().add(this.buttonsPanel, c);
        this.getContentPane().setSize(700, 300);
    }

    public String getCommentary() {
        return this.commentaryCharacter;
    }

    public String getDelimiter() {
        return this.iteratorChar;
    }

    public double getTimeUnit() {
        return this.timeUnitValue;
    }

    private void selectProcess(String process) {
        int maxRows = 40;
        String data[][] = new String[maxRows][1];
        try {
            DataReader dr = new DataReader(getDelimiter(), file, getCommentary());
            for (int i = 0; i < maxRows; i++) {
                String str;
                if (process.equals(InferenceDataImporter.columnValues)) {
                    str = dr.nextValueAt(columns);
                } else if (process.equals(InferenceDataImporter.interPacketTimes)) {
                    str = dr.nextInterPacketValueAt(columns);
                } else {
                    str = dr.nextPacketsPerTimeValueAt(columns, getTimeUnit());
                }

                if (str != null) {
                    data[i][0] = str;
                } else {
                    data[i][0] = " ";
                }

            }
            String header[] = {iFactory.getResourceString(InferenceDataImporter.column) + " " + columns};
            JTable table = new JTable(data, header);
            this.createAndShowTextPanel(table);
        } catch (IOException ioe) {
        }
    }

    /**
     * @param file
     */
    private void refreshTable(File file) {
        try {
            DataReader dr = new DataReader(this.getDelimiter(), file, this.getCommentary());
            String nextStringVector[];
            int maxRows = 25;
            String dataAux[][] = new String[maxRows][];
            String header[];
            int lineCount = 0;
            int headerLength = 0;
            while ((nextStringVector = dr.readLine()) != null && lineCount < maxRows) {
                dataAux[lineCount] = nextStringVector;
                if (dataAux[lineCount].length > headerLength) {
                    headerLength = dataAux[lineCount].length;
                }
                lineCount++;
            }
            String data[][] = new String[maxRows][headerLength];
            for (int i = 0; i < maxRows; i++) {
                if (dataAux[i] != null) {
                    for (int j = 0; j < dataAux[i].length; j++) {
                        data[i][j] = dataAux[i][j];
                    }
                    for (int j = dataAux[i].length; j < headerLength; j++) {
                        data[i][j] = " ";
                    }
                }
            }

            header = new String[headerLength];
            for (int i = 0; i < headerLength; i++) {
                header[i] = iFactory.getResourceString(InferenceDataImporter.column) + " " + i;
            }
            this.maxColumns = header.length;

            final JTable table = new JTable(data, header);
            table.addMouseListener(new MouseAdapter() {

                public void mouseClicked(MouseEvent arg0) {
                    columns = table.getSelectedColumn();
                    columnField.setText("" + columns);
                    okButton.setEnabled(true);
                }
            });

            this.createAndShowTextPanel(table);
        } catch (IOException ioe) {
        }
    }

    private void createAndShowTextPanel(JTable table) {

        this.table = table;
        scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        if (this.textPanel != null) {
            this.getContentPane().remove(this.textPanel);
        }
        this.textPanel = new JPanel(new BorderLayout());
        textPanel.add(BorderLayout.NORTH, iFactory.createLabel(InferenceDataImporter.dataPreview));
        textPanel.add(BorderLayout.CENTER, scrollPane);
        textPanel.setSize(new Dimension(550, 20));
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.WEST;
        c.gridy = 1;
        c.gridx = 0;
        c.gridwidth = GridBagConstraints.REMAINDER;
        this.getContentPane().add(this.textPanel, c);
        this.table.setColumnSelectionAllowed(true);
        this.table.setRowSelectionAllowed(false);
        this.table.setSelectionMode(0);
        setVisible(false);
        setVisible(true);

    }

    class OkAction extends AbstractAction {

        OkAction() {
            super(okAction);
        }

        public void actionPerformed(ActionEvent e) {
            if (isFirstPanel) {
                getContentPane().remove(firstTopPanel);
                GridBagConstraints c = new GridBagConstraints();
                c.anchor = GridBagConstraints.WEST;
                c.gridx = 0;
                c.gridy = 0;
                getContentPane().add(secondTopPanel, c);
                setSize(InferenceDataImporter.secondPaneDimension);
                setVisible(false);
                setVisible(true);
                isFirstPanel = false;
                columnValuesRadio.doClick();
            } else {
                String process = "";
                if (incrementProcessRadio.isSelected()) {
                    process = Inference.PACKETS_PER_UNIT;
                } else if (interPacketTimeRadio.isSelected()) {
                    process = Inference.INTER_PACKET_TIMES;
                }
                try {
                    Inference inference = new Inference(new DataReader(getDelimiter(), file, getCommentary()), columns, getTimeUnit(), process);
                    GraphicInterface.getInstance().addInternalFrame(
                            new InferenceFrame(file.getName(), inference));

                } catch (IOException ioe) {
                    // TODO auto-generated catch statement (empty)
                }
                dispose();
            }
        }
    }

    class CancelAction extends AbstractAction {

        CancelAction() {
            super(cancelAction);
        }

        public void actionPerformed(ActionEvent e) {
            dispose();
        }
    }

    class DetailsAction extends AbstractAction {

        DetailsAction() {
            super(detailsAction);
        }

        public void actionPerformed(ActionEvent e) {
        }
    }

    class TabAction extends AbstractAction {

        TabAction() {
            super(tabAction);
        }

        public void actionPerformed(ActionEvent e) {
            iteratorChar = "\t";
            columnField.setText("");
            okButton.setEnabled(false);
            refreshTable(file);
        }
    }

    class SemicolonAction extends AbstractAction {

        SemicolonAction() {
            super(semicolonAction);
        }

        public void actionPerformed(ActionEvent e) {
            iteratorChar = ";";
            columnField.setText("");
            okButton.setEnabled(false);
            refreshTable(file);
        }
    }

    class SpaceAction extends AbstractAction {

        SpaceAction() {
            super(spaceAction);
        }

        public void actionPerformed(ActionEvent e) {
            iteratorChar = " ";
            columnField.setText("");
            okButton.setEnabled(false);
            refreshTable(file);
        }
    }

    class OtherAction extends AbstractAction {

        OtherAction() {
            super(otherAction);
        }

        public void actionPerformed(ActionEvent e) {
            iteratorChar = delimiterField.getText();
            columnField.setText("");
            okButton.setEnabled(false);
            refreshTable(file);
        }
    }

    class ColumnValuesAction extends AbstractAction {

        ColumnValuesAction() {
            super(columnValuesAction);
        }

        public void actionPerformed(ActionEvent e) {
            timeUnitField.setEnabled(false);
            timeUnitLabel.setEnabled(false);
            selectProcess(InferenceDataImporter.columnValues);
        }
    }

    class InterPacketTimesAction extends AbstractAction {

        InterPacketTimesAction() {
            super(interPacketTimesAction);
        }

        public void actionPerformed(ActionEvent e) {
            timeUnitField.setEnabled(false);
            timeUnitLabel.setEnabled(false);
            selectProcess(InferenceDataImporter.interPacketTimes);
        }
    }

    class PacketsPerTimeUnitAction extends AbstractAction {

        PacketsPerTimeUnitAction() {
            super(packetsPerTimeUnitAction);
        }

        public void actionPerformed(ActionEvent e) {
            timeUnitField.setEnabled(true);
            timeUnitLabel.setEnabled(true);
            selectProcess(InferenceDataImporter.packetsPerTimeUnit);
        }
    }

    class DelimiterFieldAction extends AbstractAction {

        DelimiterFieldAction() {
            super(delimiterFieldAction);
        }

        public void actionPerformed(ActionEvent e) {
            if (otherRadioButton.isSelected()) {
                iteratorChar = delimiterField.getText();
                refreshTable(file);
            }
        }
    }

    class ColumnFieldAction extends AbstractAction {

        ColumnFieldAction() {
            super(columnFieldAction);
        }

        public void actionPerformed(ActionEvent e) {
            try {
                int columnNumber = Integer.parseInt(columnField.getText());
                if (columnNumber > maxColumns - 1) {
                    throw (new NumberFormatException());
                }
                columns = columnNumber;
                table.setColumnSelectionInterval(columns, columns);
                okButton.setEnabled(true);
            } catch (NumberFormatException nfe) {
                okButton.setEnabled(false);
                Console.showMessageDialog(
                        null,
                        iFactory.getResourceString(error)
                        + (maxColumns - 1),
                        iFactory.getResourceString(errorTitle),
                        JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    class CommentaryFieldAction extends AbstractAction {

        CommentaryFieldAction() {
            super(commentaryFieldAction);
        }

        public void actionPerformed(ActionEvent e) {
            commentaryCharacter = commentaryField.getText();
            refreshTable(file);
        }
    }

    class TimeUnitFieldAction extends AbstractAction {

        TimeUnitFieldAction() {
            super(timeUnitFieldAction);
        }

        public void actionPerformed(ActionEvent e) {
            try {
                timeUnitValue = java.lang.Double.parseDouble(timeUnitField.getText());
            } catch (NumberFormatException nfe) {
            }
            incrementProcessRadio.doClick();
        }
    }
}
